use axum::{
    extract::{Json, State},
    http::StatusCode,
    response::{IntoResponse, Response},
};
use sqlx::MySqlPool;
use crate::models::{User, UserCreateRequest, LoginRequest, UserInfo, LoginResponse};
use sha2::{Sha256, Digest};
use hex;
use jsonwebtoken::{encode, EncodingKey, Header, TokenData, Validation, DecodingKey, errors::Error as JwtError};
use serde::{Serialize, Deserialize};
use chrono::{Utc, Duration};

// JWT 的 payload 结构
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
    sub: i32,  // 用户ID
    exp: i64,  // 过期时间
    iat: i64,  // 签发时间
    username: String,
    role: String,
}

// 创建 JWT token
fn create_token(user: &User) -> Result<String, JwtError> {
    // 使用固定的密钥
    let secret = "DBHomework";
    let expiration = Utc::now()
        .checked_add_signed(Duration::hours(24))
        .expect("valid timestamp")
        .timestamp();

    let claims = Claims {
        sub: user.id,
        exp: expiration,
        iat: Utc::now().timestamp(),
        username: user.username.clone(),
        role: user.role.clone(),
    };

    encode(
        &Header::default(),
        &claims,
        &EncodingKey::from_secret(secret.as_bytes())
    )
}

pub async fn login(
    State(pool): State<MySqlPool>,
    Json(login_req): Json<LoginRequest>,
) -> Response {
    // 从数据库查询用户
    let user = 
    match sqlx::query_as::<_, User>(
    "SELECT * FROM users WHERE username = ?"
    )
    .bind(&login_req.username)
    .fetch_optional(&pool)
    .await {
        Ok(user) => user,
        Err(_) => {
            return (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(serde_json::json!({
                    "error": "用户数据库查询失败"
                }))
            ).into_response();
        }
    };

    match user {
        Some(user) => {
            // 对输入的密码进行 SHA2 加密
            let mut hasher = Sha256::new();
            hasher.update(login_req.password.as_bytes());
            let hashed_password = hex::encode(hasher.finalize());

            // 验证密码
            if hashed_password == user.password {
                // 生成 token
                let token = 
                match create_token(&user) {
                    Ok(token) => token,
                    Err(_) => {
                        return (
                            StatusCode::INTERNAL_SERVER_ERROR,
                            Json(serde_json::json!({
                                "error": "Token生成失败"
                            }))
                        ).into_response();
                    }
                };
                
                // 返回用户信息（不包含密码）
                let user_info = UserInfo {
                    id: user.id,
                    username: user.username,
                    role: user.role,
                };

                let response = LoginResponse {
                    token,
                    user: user_info,
                };

                (StatusCode::OK, Json(response)).into_response()
            } else {
                (
                    StatusCode::UNAUTHORIZED,
                    Json(serde_json::json!({
                        "error": "密码错误"
                    }))
                ).into_response()
            }
        }
        None => (
            StatusCode::UNAUTHORIZED,
            Json(serde_json::json!({
                "error": "用户不存在"
            }))
        ).into_response(),
    }
}

pub async fn getall(
    State(pool): State<MySqlPool>
) -> Response {
    match sqlx::query_as::<_, User>(
        "SELECT * FROM users"
    )
    .fetch_all(&pool)
    .await {
        Ok(results) => {
            (StatusCode::OK, Json(results)).into_response()
        },
        Err(e) => {
            println!("数据库查询错误：{:?}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(serde_json::json!({
                    "error": "数据库查询失败！"
                }))
            ).into_response()
        }
    }
}

pub async fn create(
    State(pool): State<MySqlPool>,
    Json(create_req): Json<UserCreateRequest>,
) -> Response {
    // 对密码进行 SHA2 加密
    let mut hasher = Sha256::new();
    hasher.update(create_req.password.as_bytes());
    let hashed_password = hex::encode(hasher.finalize());

    // 如果商品不存在，则创建新商品
    match sqlx::query(
        r#"
        INSERT INTO users (username, password)
        VALUES (?, ?)
        "#
    )
    .bind(&create_req.username)
    .bind(&hashed_password)
    .execute(&pool)
    .await {
        Ok(_) => {
            (StatusCode::OK, Json(serde_json::json!({
                "message": "用户创建成功"
            }))).into_response()
        },
        Err(e) => {
            println!("用户数据库插入错误：{:?}", e);
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                Json(serde_json::json!({
                    "error": "用户创建失败：用户名已存在"
                }))
            ).into_response()
        }
    }
}